package com.zhuoyue;

import com.zhuoyue.utils.PassthroughCode;

import java.util.Arrays;
import java.util.Timer;
import java.util.TimerTask;

/**
 * 写数据管理：
 *  主要提供写入
 *      1. 写入时，需要判断连接是否正在connecting，如正在connecting，则将任务放置队列。
 *      2. 写入时，需要提前将"准备工作"做好，利用空闲线程池或当前业务线程将字符串处理成byte[]，并进行透传编码。
 *      3. 写入失败，则需要将task放入队列预报下次发送。
 *      4. 连接成功后，则需要将task重新发送。
 *
 *
 *
 * @author Created by mr.liang
 */
public class WriterManagement {

    private final Timer timer;

    private final ClientConfig clientConfig;

    /** 最后一次发送时间 */
    private long lastSendTime ;

    private ConnectionManagement connectionManagement;

    private CacheTimeTaskList cacheTimeTaskList;


    public WriterManagement(ConnectionManagement connectionManagement, ClientConfig clientConfig) {
        this.connectionManagement = connectionManagement;
        this.clientConfig = clientConfig;
        this.timer = clientConfig.getTimer();
        this.cacheTimeTaskList = new CacheTimeTaskList(clientConfig,connectionManagement,timer);

        this.connectionManagement.registerCallback(v-> cacheTimeTaskList.sendCache());
    }

    /** 发送字符串数据(json) */
    public void send(String data)  {
         if(clientConfig.getThreadPoolExecutor().getActiveCount()
                == clientConfig.getThreadPoolExecutor().getMaximumPoolSize()){
            send0(data);
        }else{
            clientConfig.getThreadPoolExecutor().execute(()-> send0(data));
        }
    }

    /**
     * 发送这种情况，尽量让业务线程处理更多的事情
     *
     */
    private void send0(String data){
        //编码
        byte[] bytes = data.getBytes(clientConfig.getEncodeCharset());

        //字节填充
        bytes = PassthroughCode.encode(bytes);

        //加上分割符
        bytes = Arrays.copyOf(bytes,bytes.length + 2);
        bytes[bytes.length-1] = PassthroughCode.SPLIT_BYTES[1];
        bytes[bytes.length-2] = PassthroughCode.SPLIT_BYTES[0];


        final byte[] temp = bytes;
        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {

                if(connectionManagement.isConnecting()){
                    cacheTimeTaskList.addCache(this);
                    return ;
                }

                try {
                    connectionManagement.writerAndFlush(temp);

                    //发送成功更新时间
                    lastSendTime = System.currentTimeMillis();
                } catch (Exception e) {//这里出现异常无法解决，send里面已经try-catch住了io,我们添加到cache
                    cacheTimeTaskList.addCache(this);
                    e.printStackTrace();
                }
            }
        };


        //timer线程会被琐死
        if(connectionManagement.isConnecting()){
            cacheTimeTaskList.addCache(timerTask);
        }else{
            timer.schedule(timerTask,0);
        }

    }

    public long getLastSendTime() {
        return lastSendTime;
    }
}
